#include "XJ/XJAsduParser.h"
#include <QDebug>
#include "utils.h"
#include <QMapIterator>
#include <QMap>

XJAsduParser::XJAsduParser()
{
    // 确认定值组组号 03

    // 初始化成员变量 m_billValueGroup

}

XJAsduParser::~XJAsduParser()
{
}

bool XJAsduParser::parseRecvPacket(const QByteArray &pData, int packetLength)
{
    if (packetLength > 14)  // 最小长度14，无数据的情况下可变帧长数据
    {

        parseVariableData(pData);
    }
    else    // 固定帧长报文
    {
        qDebug() << "not ASDU10 ";
    }

    return true;
}

void XJAsduParser::parseASDU10(const QByteArray &packet)
{
    QByteArray fun = packet.mid(FUN_POSI, 2);
    QByteArray  inf = packet.mid(INF_POSI, 2);

    // 1. 通用分类数据响应命令
    if (FUN_GEN == fun && INF_EXEC_WRITE == inf) //通用分类数据响应命令（装置响应的读目录）
    {

    }
    // 2. 读指定定值组的所有条目的响应，中文名称，值，缺省值，最大最小值，步长，单位
    if ( FUN_GEN == fun && INF_READ_TITLE == inf )
    {
        parseASDU10AllValue(packet);
    }
    // 3. 读指定一个条目的描述或者值
    else if ( FUN_GEN == fun && INF_READ_GROUP == inf )
    {
        parseASDU10AllValue(packet);
    }
    else if ( FUN_GEN == fun && INF_READ_EBTRY == inf )   // 带确认的写条目响应
    {
        parseASDU10AllValue(packet);
    }
    else if ( FUN_GEN == fun && INF_EXEC_WRITE == inf ) // 带执行的写条目响应
    {
        QString rii = packet.mid(RII_POSI,2);
    }
    else
    {
        qDebug() << "unknow asdu10: "<<packet;

    }

    return;
}

bool XJAsduParser::parseVariableData(const QByteArray &pData)
{
    uchar asduType = pData.at(0);

    switch(static_cast<int>(asduType) )        // 设备回主站都是 OA 开头的回答服务
    {
        case ASDU_10_XJ:
            parseASDU10(pData);
            break;
        default:
            break;
    }

    return true;
}

vector<XJ_OneDataSetItemStruct> XJAsduParser::parseASDU10AllValue(const QByteArray &packet)           // 2021 04.24 修改为 QByteArray 类型参数
{
    // 返回的数据个数
    // 类型标识

    // 解析报文头，前7个字节
    QByteArray ngdByte = packet.mid(NGD_POSI, 2);
    int ngd_int = Utils::calNgdNo(ngdByte);
    QByteArray dataArea = packet.mid(GIN_GROUP_POSI, -1);   //从第8个开始截取报文的全部数据集元素

    qDebug() << "全部的报文数据为: " << packet;
    qDebug() << "全部的数据集为：  " << dataArea;

    // 解析用户数据段
    // 1.组号，2.条目号，3.描述类别，4.数据类型，5.数据宽度，6.数目，7.数据
    // 整个数据的长度 = 6*2 + 【数值长度】，数据宽度值等于数据长度 ， 数据宽度 * 数目

    int dataOffset = 0;     // 每一个数据的宽度都可能不一样
    vector<XJ_OneDataSetItemStruct> allData;        // 需要返回的数据
    XJ_OneDataSetItemStruct tmpDataSet;
    qDebug() << " ngd 16进制 = " << ngd_int;        // 数据集元素个数
    for (int i=0; i<ngd_int; i++)
    {
        tmpDataSet.m_ginGroup = dataArea.mid(dataOffset, 2);
        tmpDataSet.m_ginNo = dataArea.mid(dataOffset + 2, 2);
        tmpDataSet.m_kod = dataArea.mid(dataOffset + 4, 2);   //每一个数据占的字节数据
        //qDebug() << "the kod =  " << dataArea.mid(dataOffset + 4, 2);
        tmpDataSet.m_dataType = dataArea.mid(dataOffset + 6, 2);
        tmpDataSet.m_dataWidth = dataArea.mid(dataOffset + 8, 2);
        tmpDataSet.m_dataNum = dataArea.mid(dataOffset + 10, 2);

        tmpDataSet.m_dataValue = dataArea.mid(dataOffset + 12, 2* tmpDataSet.m_dataNum.toInt(nullptr,16) * tmpDataSet.m_dataWidth.toInt(nullptr,16));
        allData.push_back(tmpDataSet);

        qDebug() <<"组号=" << tmpDataSet.m_ginGroup << "条目=" << tmpDataSet.m_ginNo <<  "数据值 = " << tmpDataSet.m_dataValue << "类型 = " << tmpDataSet.m_dataType;

        dataOffset = dataOffset + ( 12 + 2 * tmpDataSet.m_dataNum.toInt(nullptr,16) * tmpDataSet.m_dataWidth.toInt(nullptr,16) );
    }


    showDataSets(allData);

    return allData;
}

 // 解析接收的报文
int XJAsduParser::recvPacketTypeFilter(const QByteArray &packet)
{
    // 对报文返回进行判断 , 1.返回信息标识符号相同 2.有效数据恢复cot=2A 3.是通用服务 4.信息序号是一个组的”F1“值或属性描述
    int type = -3;
    QByteArray asduType = packet.mid(TYP_POSI, 2);
    QByteArray fun = packet.mid(FUN_POSI, 2);
    QByteArray inf = packet.mid(INF_POSI, 2);
    QByteArray rii = packet.mid(RII_POSI, 2);
    QByteArray cot = packet.mid(COT_POSI, 2);
    QByteArray ngd = packet.mid(NGD_POSI, 2);     // 数据集元素的个数，读定值区时只有一个值， 定值组布置一个定值
    QByteArray groupNo = packet.mid(GIN_GROUP_POSI, 2);
    // 确认是否是通用分类读的有效响应

    qDebug() << "待解析的asdu基本信息 "<< asduType << cot << fun << inf;

    if ( asduType == TYPE_ASDU_OK_APPLY /*&& rii == ASDU_RII*/ && (cot == COT_S2C_GENERAL_READ_STR || cot == COT_S2C_CIRCLE_SEND_STR) && fun == FUN_GEN)
    {
        qDebug() << "有效数据响应。。。。";
        if ( inf  == INF_READ_GROUP )   // 是对一个组的读取操作
        {
            qDebug() << "对读指定组的有效数据响应。。。。";
            QByteArray kod = packet.mid(KOD_POSI, 2);
            if ( kod == KOD_DESCRIPTER )
            {
                type = REPLY_READ_SETTINGS_NAME_XJ;
            }
            else if ( kod == KOD_REAL_VALUE )
            {
                qDebug() << "读实际值的响应" << "组号 = " << QString::number(groupNo.toUInt(nullptr, 16) );
                qDebug() << "定值组号 =  " << m_billValueGroupsNo << "，当前组号 = " << groupNo.toUInt(nullptr, 16);
                if ( QString::number(groupNo.toUInt(nullptr, 16)) == m_deviceSysGroupNo && ngd == "01" )    // 是系统参数组中定值区的实际值,这个 “00" 应该是在读取标题时候确认的
                {
                    type = REPLY_READ_SETTINGS_AREA_XJ;
                    qDebug () << "读取定值区号的实际值";
                }
                //读压板组的实际值
                else if ( QString::number(groupNo.toUInt(nullptr,16)) == m_ybGroupNo )           // 实际"OE", 由读全部组的标题来确认组号哪个是压板组，哪个是定值组
                {
                    type = REPLY_READ_YB_XJ;
                }
               /* else if (groupNo == m_billValueGroup) */          // 判断是读定值组的实际值

                else if (m_billValueGroupsNo.contains(QString::number(groupNo.toUInt(nullptr, 16) )))
                {
                    qDebug () << "读取定值的实际值";
                      // 是读的定值组的全部的值
                    type = REPLY_READ_SETTINGS_CURRVALUE_XJ;
                }
            }
            else if ( kod == KOD_DEFAULT_VALU )
            {
                type = REPLY_READ_DEFAULTVALUE_XJ;
            }
            else if ( kod == KOD_DIMENSION )
            {
                type = REPLY_READ_SETTINGS_MIN_XJ;
            }
            else if ( kod == KOD_UNIT )
            {
                type = REPLY_READ_SETTINGS_UNIT_XJ;
            }
            else {
                type = -3;
            }
        }
        else if ( inf == INF_READ_TITLE )    // 只读全部组的标题
        {
            type = REPLY_TYPE_ALL_GROUP_TITLE_XJ;
        }
    }

    return  type;
}

QStringList XJAsduParser::parseBillValueNames(const QByteArray &packet)
{
    QStringList names;

    // 解析接收的报文
    XJAsduParser parser;
    vector< XJ_OneDataSetItemStruct> dataSets = parser.parseASDU10AllValue(packet);
    QString billValueGroup = "03";
    foreach (XJ_OneDataSetItemStruct it, dataSets)
    {
        // 定值的名称描述,确认读的组号
     //   if ( m_billValueGroups.contains(it.m_ginGroup) /*&&  it.m_kod == "0A"*/)
        {
            // qDebug() << "组号 " << it.m_ginGroup.toInt(nullptr,16) << ", 汉字表示： "  << Utils::GBKToUTF8(it.m_dataValue);
            //if(it.m_ginGroup == m_billValueGroup)
            names.append(Utils::GBKToUTF8(it.m_dataValue));
            qDebug() << "获取到更新的名字"  << Utils::GBKToUTF8(it.m_dataValue);
        }
    }

    return names;
}

QStringList XJAsduParser::parseBillValueUnits(const QByteArray &packet)
{
    QStringList  units;
    XJAsduParser parser;
    vector<XJ_OneDataSetItemStruct> dataSets =  parser.parseASDU10AllValue(packet);
    QString billValueGroup = "03";
    foreach (XJ_OneDataSetItemStruct it, dataSets)
    {
        // qDebug() << "组号 " << it.m_ginGroup.toInt(nullptr,16) << ", 汉字表示： "  << Utils::GBKToUTF8(it.m_dataValue);
        //if(it.m_ginGroup == m_billValueGroup)

        if ( Utils::GBKToUTF8(it.m_dataValue) == " " || Utils::GBKToUTF8(it.m_dataValue) == "" )
        {
            units.append("无");
        }
        else
        {
            units.append(Utils::GBKToUTF8(it.m_dataValue));
        }

        qDebug() << "获取到单位："  << Utils::GBKToUTF8(it.m_dataValue);
    }

    return units;
}

QStringList XJAsduParser::parseBillDimension(const QByteArray &packet)
{
    QStringList m_billValueMinList,m_billValueMaxList,m_billValueStepList;
    // 解析接收的报文
    XJAsduParser parser;
    vector<XJ_OneDataSetItemStruct> dataSets =  parser.parseASDU10AllValue(packet);
    foreach (XJ_OneDataSetItemStruct it, dataSets)
    {
        int dataWidth = it.m_dataWidth.toUInt(nullptr, 16);
        qDebug() << "读取定值的最大最小值和步长"<< it.m_dataValue;
        if (it.m_dataNum == "03" || it.m_dataNum == "02")
        {
            if( it.m_dataType == "06" || it.m_dataType == "07" ) {  // 浮点数或者短实数
                QStringList datas = Utils::parseFloatDimension(it.m_dataValue);
                qDebug() << "浮点数量程： "<< datas;
                if (Utils::parseFloatTypeMinMaxStep(it.m_dataValue).count() == 3) {
                    m_billValueMinList.append(Utils::parseFloatDimension(it.m_dataValue).at(0));
                    m_billValueMaxList.append(Utils::parseFloatDimension(it.m_dataValue).at(1));
                    m_billValueStepList.append(Utils::parseFloatDimension(it.m_dataValue).at(2));
                }
                else if (Utils::parseFloatTypeMinMaxStep(it.m_dataValue).count() == 2) {
                    m_billValueMinList.append(Utils::parseFloatTypeMinMaxStep(it.m_dataValue)[0]);
                    m_billValueMaxList.append(Utils::parseFloatTypeMinMaxStep(it.m_dataValue)[1]);
                    m_billValueStepList.append("无");
                }
                else if (Utils::parseFloatTypeMinMaxStep(it.m_dataValue).count() == 1) {    // 只有步长情况
                    m_billValueMinList.append("无");
                    m_billValueMaxList.append("无");
                    m_billValueStepList.append(Utils::parseFloatTypeMinMaxStep(it.m_dataValue)[0]);
                }
            }
            else if ( it.m_dataType == "03" )   // 无符号整数量程
            {

                qDebug() << "整数量程：" << it.m_dataValue << it.m_dataWidth << Utils::parseUIntType(it.m_dataValue, dataWidth);
                switch ( Utils::parseUIntType(it.m_dataValue, dataWidth).count())
                {
                case 0 :
                    m_billValueMinList.append("no");
                    m_billValueMaxList.append("no");
                    m_billValueStepList.append("no");
                    break;
                case 1 :
                    m_billValueMinList.append("no");
                    m_billValueMaxList.append("no");
                    m_billValueStepList.append(Utils::parseUIntType(it.m_dataValue, dataWidth)[0]);
                    break;
                case 2 :
                    m_billValueMinList.append(Utils::parseUIntType(it.m_dataValue, dataWidth)[0]);
                    m_billValueMaxList.append(Utils::parseUIntType(it.m_dataValue, dataWidth)[1]);
                    m_billValueStepList.append("no");
                    break;
                case 3:
                    m_billValueMinList.append(Utils::parseUIntType(it.m_dataValue, dataWidth)[0]);
                    m_billValueMaxList.append(Utils::parseUIntType(it.m_dataValue, dataWidth)[1]);
                    m_billValueStepList.append(Utils::parseUIntType(it.m_dataValue, dataWidth)[2]);
                    break;
                }
            }
            else if( it.m_dataType == "04")
            {
                int intDataWidth = it.m_dataWidth.toUInt(nullptr,16);
                qDebug() << "整数量程：" << it.m_dataValue << it.m_dataWidth << Utils::parseIntTypeMinMaxStep(it.m_dataValue, intDataWidth);
                QStringList dataValueList = Utils::parseIntTypeMinMaxStep(it.m_dataValue, intDataWidth);
                switch ( dataValueList.count())
                {
                case 0 :
                    m_billValueMinList.append("no");
                    m_billValueMaxList.append("no");
                    m_billValueStepList.append("no");
                    break;
                case 1 :
                    m_billValueMinList.append("no");
                    m_billValueMaxList.append("no");
                    m_billValueStepList.append(Utils::hexStrToIntStr(dataValueList[0]));
                    break;
                case 2 :
                    m_billValueMinList.append(dataValueList[0]);;
                    m_billValueMaxList.append(dataValueList[1]);
                    m_billValueStepList.append("无");
                    break;
                case 3 :
                    m_billValueMinList.append( dataValueList[0]);
                    m_billValueMaxList.append( dataValueList[1] );
                    m_billValueStepList.append( dataValueList[2] );
                    break;
                }
            }
            else if (it.m_dataType == "01" )  // ASCII8位码量程,都是不存在最大最小步长值的
            {
                qDebug() << "ASCII8位码 " << it.m_dataValue << it.m_dataWidth << Utils::parseASCII8BTypeMinMaxStepUnit(it.m_dataValue);
                if (Utils::parseASCII8BTypeMinMaxStepUnit(it.m_dataValue).count() ==0 )
                {
                    m_billValueMinList.append("无");
                    m_billValueMaxList.append("无");
                    m_billValueStepList.append("无");
                }
                else if (Utils::parseASCII8BTypeMinMaxStepUnit(it.m_dataValue).count() ==1 )
                {
                    QString  strList = Utils::parseASCII8BTypeMinMaxStepUnit(it.m_dataValue);
                    m_billValueMinList.append("无");
                    m_billValueMaxList.append("无");
                    m_billValueStepList.append(strList);
                }
                else if (Utils::parseASCII8BTypeMinMaxStepUnit(it.m_dataValue).count() ==2 )
                {
                    QString  strList = Utils::parseASCII8BTypeMinMaxStepUnit(it.m_dataValue);
                    m_billValueMinList.append(Utils::mixCharToWord(strList, dataWidth)[0]);
                    m_billValueMaxList.append(Utils::mixCharToWord(strList, dataWidth)[1]);
                    m_billValueStepList.append("无");
                }
                else
                {
                    QString  strList = Utils::parseASCII8BTypeMinMaxStepUnit((QString)it.m_dataValue);
                    // 将strList按照 单个宽度进行分割
                    qDebug() << "ASCII8位码量程：" <<it.m_dataType <<Utils::mixCharToWord(strList, dataWidth);
                    m_billValueMinList.append(Utils::mixCharToWord(strList, dataWidth).at(0));
                    m_billValueMaxList.append(Utils::mixCharToWord(strList, dataWidth).at(0));
                    m_billValueStepList.append(Utils::mixCharToWord(strList, dataWidth).at(0));
                }
            }
        }
    }
    QStringList ret =  (m_billValueMinList + m_billValueMaxList + m_billValueStepList);

    return ret;
}

QStringList XJAsduParser::parseBillInfo(const int replyType, const QByteArray &packet)
{
    QStringList result;

    // 获取当前响应的组号
    QString groupNo = Utils::hexNumToDecNum(packet.mid(GIN_GROUP_POSI, 2));
    qDebug() << "*******解析table info ********* 组号 = " << groupNo;
    //  当非第一次请求的时候应该将 m_billTablesMap 清空

    switch (replyType)
    {
    case REPLY_TYPE_ALL_GROUP_TITLE_XJ:
        result = parseBillTitles(packet);
        break;
    case REPLY_READ_SETTINGS_NAME_XJ:
        result = parseBillValueNames(packet);
        qDebug() << "********定值名字结果********" << result;
        m_billTablesMap[groupNo].billNameList.append(result);
        break;
    case REPLY_READ_SETTINGS_CURRVALUE_XJ: //目前不能读取实际定值的值
        result = parseBillRealValue(packet);
        m_billTablesMap[groupNo].billRealValueList.append(result);
        break;
    case REPLY_READ_DEFAULTVALUE_XJ:
        result = parseBillDefaultValue(packet) + parseBillValueDataTypes(packet);
        m_billTablesMap[groupNo].billDefaultValueList.append(parseBillDefaultValue(packet));
        m_billTablesMap[groupNo].billTypeList.append(parseBillValueDataTypes(packet));
        break;
    case REPLY_READ_SETTINGS_MIN_XJ:
        result = parseBillDimension(packet);
        m_billTablesMap[groupNo].billMinList.append(result.mid(0, result.count()/3));
        m_billTablesMap[groupNo].billMaxList.append(result.mid( result.count()/3, result.count()));
        m_billTablesMap[groupNo].billStepsList.append(result.mid( result.count()/3*2, result.count()));
        break;
    case REPLY_READ_SETTINGS_UNIT_XJ:
        result = parseBillValueUnits(packet);
        m_billTablesMap[groupNo].billUnitList.append(result);
        break;
    case REPLY_READ_SETTINGS_AREA_XJ:
        result = parseBillArea(packet);
        break;
    default:
        result = parseBillUnkown(packet);   // 未知类型
        break;
    }

    return result;
}

void XJAsduParser::clearBillTableBuffer()
{
//    m_billTables.clear();
    m_billTablesMap.clear();
}

void XJAsduParser::getBillRelationGroupNos(QMap<QString, QString> &groupNoAndName)
{
    QMap<QString,QString>::iterator it;
    for (it = groupNoAndName.begin(); it!=groupNoAndName.end(); ++it)
    {
        QString groupNoStrDec =  QString::number(it.key().toUInt(nullptr, 16));
        if (it.value().contains("定值"))
        {
            if (!m_billValueGroupsNo.contains(it.key())) {
                qDebug() << "发现一个定值组 = " << it.key();       // 定值区号 key = "220"
                m_billValueGroupsNo.push_back(groupNoStrDec);
            }
            struct XJ_BillTableStruct tmpTable;
            tmpTable.groupName = it.value();
            tmpTable.groupNo = groupNoStrDec;
            m_billTables.append(tmpTable);
            m_billTablesMap[groupNoStrDec] = tmpTable;
        }
        else if ( it.value().contains("系统") )
        {
            m_deviceSysGroupNo =groupNoStrDec;
        }
        else if ( it.value().contains("压板") )
        {
            m_ybGroupNo = groupNoStrDec;
        }
    }
}

QStringList XJAsduParser::parseBillTitles(const QByteArray &packet)
{
    vector<XJ_OneDataSetItemStruct> dataSets = parseASDU10AllValue(packet);
    QStringList titiles;
    QStringList groupNoes;
    foreach (XJ_OneDataSetItemStruct it, dataSets)
    {
        titiles.push_back(it.m_ginGroup);      // 同时添加到组号
        // 进行简单的判断确认数据正确
        groupNoes.push_back(Utils::GBKToUTF8(it.m_dataValue));
        qDebug() << "添加一个组号和一个" << Utils::hexNumToDecNum(it.m_ginGroup) << Utils::GBKToUTF8(it.m_dataValue);
    }

    getBillTitleGroupNo(packet);

    return titiles+groupNoes;
}

QStringList XJAsduParser::parseBillArea(const QByteArray &packet)
{
    vector<XJ_OneDataSetItemStruct> dataSets = parseASDU10AllValue(packet);
    QStringList areaValue;
    foreach (XJ_OneDataSetItemStruct it, dataSets)
    {
        // qDebug() << "定值区号： " << Utils::parseUIntType(it.m_dataValue, it.m_dataWidth.toUInt(nullptr,16));
        areaValue.append(Utils::parseUIntType(it.m_dataValue, it.m_dataWidth.toUInt(nullptr,16)));
    }

    return areaValue;
}

QStringList XJAsduParser::parseBillDefaultValue(const QByteArray &packet)
{
    // 实际数据,缺省值，准确度
    // 解析接收的报文
    vector<XJ_OneDataSetItemStruct> dataSets =  parseASDU10AllValue(packet);
    QString billValueGroup = "03";
    QStringList billValueDefaultList;         // 存放默认值
    foreach (XJ_OneDataSetItemStruct it, dataSets)
    {
       // if (/*it.m_kod == "01" ||*/ it.m_kod == "02" /*|| it.m_kod == "05"*/)
        {
            ///qDebug() << "数据" << ++i << it.m_dataValue;
            if (it.m_dataType == "00")
            {
                qDebug() << "数据无所对应的类型";
                billValueDefaultList.append(" ");
            }
            else if (it.m_dataType == "01")
            {
                qDebug() << "数据类型为 OS8ASCII" << Utils::parseASCII8BTypeMinMaxStepUnit(it.m_dataValue);
                billValueDefaultList.append(Utils::parseASCII8BTypeMinMaxStepUnit(it.m_dataValue));
            }
            else if (it.m_dataType == "03")
            {
                qDebug() << "数据类型为无符号整数" << (Utils::reverseStr(it.m_dataValue).toUInt(nullptr,10));
                billValueDefaultList.append(QString::number((Utils::reverseStr(it.m_dataValue).toUInt(nullptr,10))));
            }
            else if( it.m_dataType == "06")
            {
                qDebug() << "数据类型为浮点数" << it.m_dataValue.toFloat(nullptr);     // IEEE 754 短实数
                billValueDefaultList.append(QString::number(it.m_dataValue.toFloat(nullptr)));
            }
            else if (it.m_dataType == "07")      // 数据类型为短实数
            {
                qDebug() <<"数据类型为短实数: " << it.m_dataValue.toUShort(nullptr, 16);
                billValueDefaultList.append(QString::number(it.m_dataValue.toUInt(nullptr, 16)));
            }
            else if (it.m_dataType == "09")
            {
                qDebug() << "数据类型为双点信息" << (Utils::reverseStr(it.m_dataValue)).toInt();        // bool 类型值
                billValueDefaultList.append(Utils::reverseStr(it.m_dataValue));
            }
            else
            {
                if (it.m_dataType == "10")
                {
                    qDebug() << "数据类型为单点信息";
                }
                else if (it.m_dataType == "0C")
                {
                    qDebug() << "数据类型为带品质描述的被测值";
                }
                else if (it.m_dataType == "13")
                {
                    qDebug() << "数据类型为带时标的报文";
                }
                else if (it.m_dataType == "18")
                {
                    qDebug() << "数据类型为数据结构";
                }
                else if (it.m_dataType == "CB")
                {
                    qDebug() << "数据类型为带7字节的时标报文";
                }
                else if (it.m_dataType == "CC")
                {
                    qDebug() << "数据类型为带相对时间的7字节时标报文";
                }
                else if(it.m_dataType == "00")
                {
                    qDebug() << "数据类型为无所确定的类型";
                }
            }
        }
    }

    return billValueDefaultList;
}

QStringList XJAsduParser::parseBillRealValue(const QByteArray &packet)
{
    // 实际数据,缺省值，准确度
    // 解析接收的报文
    vector<XJ_OneDataSetItemStruct> dataSets =  parseASDU10AllValue(packet);
    QStringList billValueList;         // 存放默认值
    foreach (XJ_OneDataSetItemStruct it, dataSets)
    {
        ///qDebug() << "数据" << ++i << it.m_dataValue;
        if (it.m_dataType == "00")
        {
            qDebug() << "数据无所对应的类型";
            billValueList.append(" ");
        }
        else if (it.m_dataType == "01")
        {
            qDebug() << "数据类型为 OS8ASCII" << Utils::parseASCII8BTypeMinMaxStepUnit(it.m_dataValue);
            billValueList.append(Utils::parseASCII8BTypeMinMaxStepUnit(it.m_dataValue));
        }
        else if (it.m_dataType == "03")
        {
            qDebug() << "数据类型为无符号整数" << (Utils::reverseStr(it.m_dataValue).toUInt(nullptr, 16));
            billValueList.append(QString::number((Utils::reverseStr(it.m_dataValue).toUInt(nullptr, 16))));
        }
        else if(it.m_dataType == "04")
        {
            qDebug() << "数据类型为整数" << it.m_dataValue;
            billValueList.append( Utils::hexStrToIntStr(it.m_dataValue) );
        }
        else if( it.m_dataType == "06")
        {
            qDebug() << "数据类型为浮点数" << Utils::hexStrToFloat(it.m_dataValue);     // IEEE 754 短实数
            billValueList.append(QString::number(Utils::hexStrToFloat(it.m_dataValue)));
        }
        else if (it.m_dataType == "07")      // 数据类型为短实数
        {
            qDebug() <<"数据类型为短实数: " << Utils::hexStrToFloat(it.m_dataValue);
            billValueList.append( QString::number(Utils::hexStrToFloat(it.m_dataValue)));
        }
        else if (it.m_dataType == "09")
        {
            qDebug() << "数据类型为双点信息" << (Utils::reverseStr(it.m_dataValue)).toInt();        // bool 类型值
            billValueList.append(Utils::reverseStr(it.m_dataValue));
        }
        else
        {
            if (it.m_dataType == "10")
            {
                qDebug() << "数据类型为单点信息";
            }
            else if (it.m_dataType == "0C")
            {
                qDebug() << "数据类型为带品质描述的被测值";
            }
            else if (it.m_dataType == "13")
            {
                qDebug() << "数据类型为带时标的报文";
            }
            else if (it.m_dataType == "18")
            {
                qDebug() << "数据类型为数据结构";
            }
            else if (it.m_dataType == "CB")
            {
                qDebug() << "数据类型为带7字节的时标报文";
            }
            else if (it.m_dataType == "CC")
            {
                qDebug() << "数据类型为带相对时间的7字节时标报文";
            }
            else if(it.m_dataType == "00")
            {
                qDebug() << "数据类型为无所确定的类型";
            }
        }
    }

    return billValueList;
}

QStringList XJAsduParser::parseBillUnkown(const QByteArray &packet)
{
    QStringList unknow = {"0"};
    return unknow;
}

// 解析定值数据类型，在解析默认值的时候就可以确认
QStringList XJAsduParser::parseBillValueDataTypes(const QByteArray &packet)
{
    // 实际数据,缺省值，准确度
    // 解析接收的报文
    vector<XJ_OneDataSetItemStruct> dataSets =  parseASDU10AllValue(packet);
    QString billValueGroup = "03";
    QStringList dataTypes;         // 存放默认值
    foreach (XJ_OneDataSetItemStruct it, dataSets)
    {
        qDebug() << "数据无所对应的类型";
        dataTypes.append(it.m_dataType);
    }

    return dataTypes;
}

void  XJAsduParser::getBillTitleGroupNo(const QByteArray &packet)
{
    vector<XJ_OneDataSetItemStruct> dataSets  = parseASDU10AllValue(packet);
    foreach (XJ_OneDataSetItemStruct it, dataSets)
    {
        if (!m_groupNoNameMap.keys().contains(it.m_ginGroup) ){
            m_groupNoNameMap [it.m_ginGroup] = Utils::GBKToUTF8(it.m_dataValue);
        }
        qDebug() << "添加一个组号和一个" << it.m_ginGroup.toUInt(nullptr, 16) << Utils::GBKToUTF8(it.m_dataValue) ;
    }

    // 获取定值组组号信息
    getBillRelationGroupNos(m_groupNoNameMap);
}


void XJAsduParser::showDataSets(vector<XJ_OneDataSetItemStruct> &dataSets)
{
    //根据数据类型来分
    int i=0;
    foreach (XJ_OneDataSetItemStruct it, dataSets)
    {
        // 定值的名称描述
        if (it.m_kod == "0A")
        {
            qDebug() << "数据 " << ++i << it.m_dataValue;
            qDebug() << "组号 " << it.m_ginGroup << ", 汉字表示： "  << Utils::GBKToUTF8(it.m_dataValue);
            //if(it.m_ginGroup == m_billValueGroup)
            m_billValueName.append(Utils::GBKToUTF8(it.m_dataValue));
        }
         // 实际数据,缺省值，准确度
        else if (it.m_kod == "01" || it.m_kod == "02")
        {
            ///qDebug() << "数据" << ++i << it.m_dataValue;
            if (it.m_dataType == "00")
            {
                qDebug() << "数据无所对应的类型";
                m_billValueDefaultList.append(" ");
            }
            else if (it.m_dataType == "01")
            {
                qDebug() << "数据类型为 OS8ASCII" << Utils::parseASCII8BTypeMinMaxStepUnit(it.m_dataValue);
                m_billValueDefaultList.append(Utils::parseASCII8BTypeMinMaxStepUnit(it.m_dataValue));
            }
            else if (it.m_dataType == "03")
            {
                qDebug() << "数据类型为无符号整数" << (it.m_dataValue).toInt(nullptr, 16);
                m_billValueDefaultList.append(QString::number((it.m_dataValue).toInt(nullptr, 16)));
            }
            else if ( it.m_dataType == "06")
            {
                qDebug() << "数据类型为浮点数" <<it.m_dataValue.toFloat();     // IEEE 754 短实数
                m_billValueDefaultList.append(QString::number(it.m_dataValue.toFloat()));
            }
            else if (it.m_dataType == "07")      // 数据类型为短实数
            {
                qDebug() <<"数据类型为短实数: " << it.m_dataValue.toUShort();
                m_billValueDefaultList.append( QString::number( Utils::hexStrToFloat(it.m_dataValue)));
            }
            else if (it.m_dataType == "09")
            {
                qDebug() << "数据类型为双点信息" << (Utils::reverseStr(it.m_dataValue)).toInt();        // bool 类型值
                m_billValueDefaultList.append(Utils::reverseStr(it.m_dataValue));
            }
            else if (it.m_dataType == "10")
            {
                qDebug() << "数据类型为单点信息";
            }
            else if (it.m_dataType == "0C")
            {
                qDebug() << "数据类型为带品质描述的被测值";
            }
            else if (it.m_dataType == "13")
            {
                qDebug() << "数据类型为带时标的报文";
            }
            else if (it.m_dataType == "18")
            {
                qDebug() << "数据类型为数据结构";
            }
            else if (it.m_dataType == "CB")
            {
                qDebug() << "数据类型为带7字节的时标报文";
            }
            else if (it.m_dataType == "CC")
            {
                qDebug() << "数据类型为带相对时间的7字节时标报文";
            }
            else if(it.m_dataType == "00")
            {
                qDebug() << "数据类型为无所确定的类型";
            }
        }
        //最大值最小值步长
        else if (it.m_kod == "03")
        {
            qDebug() << "读取定值的最大最小值和步长"<< it.m_dataValue;
            if (it.m_dataNum =="03" || it.m_dataNum == "02")
            {
                if( it.m_dataType == "06" || it.m_dataType == "07") // 浮点数或者短实数
                {
                    qDebug() << "浮点数量程： "<<Utils::parseFloatTypeMinMaxStep(it.m_dataValue);
                    m_billValueMinList.append(Utils::parseFloatTypeMinMaxStep(it.m_dataValue)[0]);
                    m_billValueMaxList.append(Utils::parseFloatTypeMinMaxStep(it.m_dataValue)[1]);
                    m_billValueStepList.append(Utils::parseFloatTypeMinMaxStep(it.m_dataValue)[2]);
                }
                else if ( it.m_dataType == "03" )   // 整数量程
                {
                    qDebug() << "整数量程：" << it.m_dataValue << it.m_dataWidth << Utils::parseUIntType(it.m_dataValue, it.m_dataWidth.toUInt(nullptr,16));

                    switch ( it.m_dataNum.toUInt(nullptr, 16))
                    {
                        case 0 :
                        m_billValueMinList.append("no");
                        m_billValueMaxList.append("no");
                        m_billValueStepList.append("no");
                        break;
                    case 1 :
                        m_billValueMinList.append("no");
                        m_billValueMaxList.append("no");
                        m_billValueStepList.append(Utils::parseUIntType(it.m_dataValue,it.m_dataWidth.toUInt(nullptr,10))[0]);
                        break;
                    case 2 :
                        m_billValueMinList.append(Utils::parseUIntType(it.m_dataValue,it.m_dataWidth.toUInt(nullptr,10))[0]);
                        m_billValueMaxList.append(Utils::parseUIntType(it.m_dataValue,it.m_dataWidth.toUInt(nullptr,10))[1]);
                        m_billValueStepList.append("no");
                        break;
                    case 3:
                        m_billValueMinList.append(Utils::parseUIntType(it.m_dataValue,it.m_dataWidth.toUInt(nullptr,10))[0]);
                        m_billValueMaxList.append(Utils::parseUIntType(it.m_dataValue,it.m_dataWidth.toUInt(nullptr,10))[1]);
                        m_billValueStepList.append(Utils::parseUIntType(it.m_dataValue,it.m_dataWidth.toUInt(nullptr,10))[2]);
                        break;
                    }
                }
                else if (it.m_dataType == "01")  // ASCII8位码
                {
                    if(Utils::parseASCII8BTypeMinMaxStepUnit(it.m_dataValue).count() !=3)
                    {
                        m_billValueMinList.append(" ");
                        m_billValueMaxList.append(" ");
                        m_billValueStepList.append(" ");
                    }
                    int width = it.m_dataWidth.toInt(nullptr,16);
                    QString  strList = Utils::parseASCII8BTypeMinMaxStepUnit(it.m_dataValue);
                    // 将strList按照 单个宽度进行分割
                    qDebug() << "ASCII8位码量程：" <<Utils::mixCharToWord(strList,width);
                    this->m_billValueMinList.append(Utils::mixCharToWord(strList,width)[0]);
                    m_billValueMaxList.append(Utils::mixCharToWord(strList,width)[1]);
                    m_billValueStepList.append(Utils::mixCharToWord(strList,width)[2]);
                }
            }
        }
        // 读取单位
        else if (it.m_kod == "09")
        {
          // qDebug() << "单位" <<  Utils::mixCharToWord(Utils::parseASCII8BTypeMinMaxStepUnit(it.m_dataValue),it.m_dataWidth.toInt(nullptr,16));
           qDebug() << "单位 GBKTOUTF8 :" << Utils::GBKToUTF8(it.m_dataValue);
           m_billValueUinitList.append( Utils::GBKToUTF8(it.m_dataValue) );
        }
    }
}

QString XJAsduParser::findGroupNoByGroupName(const QString &groupName, vector<XJ_OneDataSetItemStruct> &dataSets)
{
    foreach (XJ_OneDataSetItemStruct it, dataSets)
    {
        if (it.m_kod == "0A" && Utils::GBKToUTF8(it.m_dataValue) == groupName )
        {
            return it.m_ginGroup;
        }
    }
    qDebug() << "not find the group.";

    return nullptr;
}

